package hacky.filebased.agent;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.net.URL;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ConTestInstrumentationMainBasedClassFileTransformerTest {
    private static final String TEMP_DIR_PROP = ConTestInstrumentationMainBasedClassFileTransformer.CON_TEST_INSTRUMENTATION_TEMP_DIR;
    private ConTestInstrumentationMainBasedClassFileTransformer transformer;
    private String thisClassName;
    private String thisClassFileName;
    private File thisClassFile;
    private File tempDirectory;
    private String originalPropertyValue;

    @Before
    public void setup() {
        resetTempDirProperty();
        transformer = new ConTestInstrumentationMainBasedClassFileTransformer();
        transformer.deleteFilesAfterTransformation = false;
        tempDirectory = transformer.getTempDirectory();
        thisClassName = getClass().getName().replaceAll("[.]", "/");
        thisClassFileName = thisClassName + ".class";
        thisClassFile = getClassFileForThisTestClass(thisClassFileName);
        assertTrue(thisClassFile.exists());
    }

    private void resetTempDirProperty() {
        originalPropertyValue = System.getProperty(TEMP_DIR_PROP);
        System.setProperty(TEMP_DIR_PROP, "TEST_TEMP_DIR");
    }

    @After
    public void resetProperty() {
        if (originalPropertyValue == null)
            System.clearProperty(TEMP_DIR_PROP);
        else
            System.setProperty(TEMP_DIR_PROP, originalPropertyValue);
    }

    @Test
    public void canTransformOneFile() throws Exception {

        byte[] originalFileBytes = FileUtilities.readFileFully(thisClassFile);
        assertNotNull(originalFileBytes);
        transformer.transform(null, thisClassName, null, null, originalFileBytes);

        File instrumentedFile = FileUtilities.generateDestinationFile(thisClassName, tempDirectory);

        byte[] instrumentedFileBytes = getInstrumentedFileAsByteArray();

        removeGeneratedFiles(instrumentedFile);

        assertTrue(originalFileBytes.length < instrumentedFileBytes.length);
    }

    private void removeGeneratedFiles(File instrumentedFile) {
        FileUtilities.removeFile(instrumentedFile);
        FileUtilities.removeFile(new File(instrumentedFile.getAbsoluteFile() + "_backup"));
    }

    private byte[] getInstrumentedFileAsByteArray() {
        File instrumentedFile = FileUtilities.generateDestinationFile(thisClassName, tempDirectory);
        return FileUtilities.readFileFully(instrumentedFile);
    }

    private File getClassFileForThisTestClass(String thisClassFileName) {
        URL url = getClass().getClassLoader().getResource(thisClassFileName);
        File thisClassFile = new File(url.getFile());
        return thisClassFile;
    }
}
